﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using Model;
using Rectangle = Model.Rectangle;

namespace PaintHW
{
    public partial class Form1 : Form
    {
        private IPaintAppModel theModel;
        private Color currentColor = Color.Black; //Default Color is Black
        private Color[,] colorPalette =
        {
            //First Row of Colors for the Color Palette
            {
                Color.Black, Color.White, Color.Green, Color.Yellow,Color.Purple, Color.Pink,Color.Red,
                Color.PowderBlue,Color.RosyBrown, Color.GreenYellow
            },
            //Second Row of Colors for the Color Palette
            {
                Color.PaleVioletRed, Color.DarkViolet, Color.Orange, Color.OrangeRed,Color.PaleGreen, Color.Silver,
                Color.SteelBlue, Color.Blue,Color.Tomato, Color.Tan
            }
        };
        private Point firstPoint; //Used for the First Point to create a Shape
        private Point endPoint; //Used for the End Point to create a Shape
        private int borderWidth = 1; //Width in pixels for the Brush

        public Form1(IPaintAppModel theModel)
        {
            this.theModel = theModel;
            InitializeComponent();
            InitializeColorPalette();
            AttachMouseEventsToCanvas();
        }

        /// <summary>
        /// Attaches the MouseUp and MouseDown Event Handlers to the canvas panel
        /// </summary>
        private void AttachMouseEventsToCanvas()
        {
            this.canvas.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CanvasOnMouseDown);
            this.canvas.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CanvasOnMouseUp);
        }
        /// <summary>
        /// Initializes the Color Palette
        /// </summary>
        private void InitializeColorPalette()
        {
            for (int i = 0; i < colorPalette.GetLength(0); i++)
            {
                for (int j = 0; j < colorPalette.GetLength(1); j++)
                {
                    //Create a custom button
                    var button = new Button
                    {
                        Dock = System.Windows.Forms.DockStyle.Fill,
                        Margin = Padding.Empty,
                        BackColor = colorPalette[i, j]
                    };
                    button.Click += new System.EventHandler(ChangeCurrentColor);
                    this.colorPaletteTablePanelLayout.Controls.Add(button, j, i);
                }
            }
        }

        /// <summary>
        /// Displays the Color DialogBox. If the user clicks OK then the current color
        /// will change to the color that was selected
        /// </summary>
        /// <param name="sender">the sender object</param>
        /// <param name="e">the EventArgs of the event</param>
        private void showColorDialogButton_Click(object sender, EventArgs e)
        {
            DialogResult result = colorDialog1.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                currentColor = colorDialog1.Color;
                currentColorButton.BackColor = currentColor;
            }
        }

        /// <summary>
        /// Called when a User Clicks a Color from the Color Palette. The Current Color will be changed to
        /// the Color that was pressed in the Palette
        /// </summary>
        /// <param name="sender">the object that raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void ChangeCurrentColor(object sender, EventArgs e)
        {
            var button = sender as Button;
            currentColor = button.BackColor;
            currentColorButton.BackColor = currentColor;
        }
        /// <summary>
        /// Called when the OnMouseDown Event is raised on the Canvas
        /// </summary>
        /// <param name="sender">the object that raised raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void CanvasOnMouseDown(object sender, MouseEventArgs e)
        {
            firstPoint = new Point(e.X, e.Y);
        }
        /// <summary>
        /// Called when the OnMouseDown Event is raised on the Canvas
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CanvasOnMouseUp(object sender, MouseEventArgs e)
        {
            endPoint = new Point(e.X, e.Y);
            Shape s = CreateShape();
            if (s != null)
                this.theModel.Shapes.Add(s);
            OnCanvasPaint(sender,new PaintEventArgs(canvas.CreateGraphics(),canvas.Bounds));
        }
        /// <summary>
        /// Changes the crushSelector to the Current value selected in the brushSelector ComboBox
        /// </summary>
        /// <param name="sender">the object that raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void brushSelector_SelectedIndexChanged(object sender, EventArgs e)
        {
            var selected = sender as ComboBox;
            if (selected.Text == "Fill")
            {
                DisableComboBoxes();
            }
            else
            {
                EnableComboBoxes();
            }
        }

        /// <summary>
        /// Disables the shapeSelector and borderWidth ComboBoxes
        /// </summary>
        private void DisableComboBoxes()
        {
            shapeSelector.Enabled = false;
            borderSelector.Enabled = false;
        }
        /// <summary>
        /// Enables the shapeSelector and borderWidth ComboBoxes
        /// </summary>
        private void EnableComboBoxes()
        {
            shapeSelector.Enabled = true;
            borderSelector.Enabled = true;
        }
        /// <summary>
        /// Creates a Shape based off of the current settings
        /// </summary>
        private Shape CreateShape()
        {
            if (shapeSelector.SelectedIndex != -1)//Nothing Selected-ComboBox is in initial state
            {
                if (brushSelector.SelectedText != "Fill") //Not in Fill mode
                    //TODO Implement Fill Mode
                {
                    var shape = BuildShape.ShapeBuilder(firstPoint, shapeSelector.SelectedIndex.ToString());
                    SetShapeProperties(shape);
                    return shape;
                }
            }
            return null;
        }
        /// <summary>
        /// Sets the specified shape's properties with the current settings
        /// </summary>
        /// <param name="shape">the shape to set</param>
        private void SetShapeProperties(Shape shape)
        {
            shape.LastPoint = endPoint;
            shape.Color = currentColor;
            shape.BorderWidth = borderWidth;
        }

        /// <summary>
        /// Changes the Canvas's BackgroundImage to the selected Image
        /// </summary>
        /// <param name="sender">the object that raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = this.openPictureDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                theModel.Open(openPictureDialog.FileName);
            }
        }

        /// <summary>
        /// Changes the border width to the value represented by the value selected in the border
        /// selection ComboBox
        /// </summary>
        /// <param name="sender">the object that raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void borderSelector_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch(borderSelector.SelectedIndex)
            {
                case  0: //Small
                    borderWidth = 1;
                    break;
                case 1: //Medium
                    borderWidth = 3;
                    break;
                case 2: //Extra-Medium
                    borderWidth = 5;
                    break;
                case 3: //Large
                    borderWidth = 9;
                    break;
                default:
                    borderWidth = 1;
                    break;
            }
        }

        /// <summary>
        /// Brings up the saveFileDialog to save the Canvas Picture
        /// </summary>
        /// <param name="sender">the object that raised the Event</param>
        /// <param name="e">A System.EventArgs that contains the event data</param>
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = savePictureDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                theModel.Save(savePictureDialog.FileName);
            }
        }

        /// <summary>
        /// Paints the Canvas when the OnPaint method is invoked on the panel
        /// </summary>
        /// <param name="sender">the object that invoked that raised the Event</param>
        /// <param name="e">the PaintEventArgs</param>
        protected void OnCanvasPaint(object sender, PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics gfx = e.Graphics;
            foreach (var shape in theModel.Shapes)
            {
                shape.Draw(gfx);
            }
        }
    }
}